/**
 * 
 */
package com.tvshows.structure.bdd;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.tvshows.structure.beans.Favorite;
import com.tvshows.structure.beans.Property;
import com.tvshows.structure.log.LoggingTreatment;

/**
 * @author tMidy
 * <p>
 * Class managing queries to the database
 * </p>
 */
public class BddQueries
{

    /**
     * Hibernate Util
     */
    private final HibernateUtil hibernateUtil;

    /**
     * The transaction
     */
    private Transaction transaction;

    /**
     * Tye db session
     */
    private Session session = null;

    /**
     * The bddQueries
     */
    private static BddQueries bddQueries;

    /**
     * The logger
     */
    Logger logger = Logger.getLogger( BddQueries.class );

    /**
     * The favorites list
     */
    private List<Favorite> favoritesList;

    /**
     * Sql actif
     */
    private boolean sqlActive = true;

    /**
     * If the refresh job is running
     */
    private boolean isJobRunning = false;

    /**
     * Constructor of the class
     */
    public BddQueries()
    {
        hibernateUtil = new HibernateUtil();
    }

    /**
     * @return the favorites table
     */
    @SuppressWarnings( "unchecked" )
    public List<Favorite> loadFavorites()
    {

        if ( favoritesList != null )
        {
            return favoritesList;
        }

        try
        {
            initTransaction();
            if ( session != null )
            {
                favoritesList = session.createQuery( "from Favorite order by FAVORITE_NAME" ).list();

                hibernateUtil.closeConnection( transaction, session );

                return favoritesList;
            }
        }
        catch ( Exception e )
        {
            logger.error( e.getMessage() );
        }

        return new ArrayList<Favorite>();

    }

    /**
     * Adds a favorite
     * 
     * @param nameFavorite the name of the favorite
     * @param seasonNumber The season number
     * @param lastEpisodeNumber the last episode number
     */
    public void addFavorite( String nameFavorite, String seasonNumber, String lastEpisodeNumber )
    {
        Favorite favorite = new Favorite();
        favorite.setLastEpisodeNumber( lastEpisodeNumber );
        favorite.setNameFavorite( nameFavorite );
        favorite.setSeasonNumber( seasonNumber );

        initTransaction();
        if ( session != null )
        {
            session.save( favorite );
            endConnection();
        }

            getFavoritesList().add( favorite );
            sort( favoritesList );
    }

    /**
     * Orders by name the shows
     * 
     * @param favoritesList the list of favorite shows
     */
    private void sort( List<Favorite> favoritesList )
    {
        Collections.sort( favoritesList, new Comparator<Favorite>()
        {
            @Override
            public int compare( Favorite f1, Favorite f2 )
            {
                return f1.getNameFavorite().compareTo( f2.getNameFavorite() );
            }
        } );

    }

    /**
     * Deletes a favorite
     * 
     * @param nameFavorite the favorite to delete
     */
    public void deleteFavorite( String nameFavorite )
    {
        Favorite favorite = null;
        initTransaction();

        if ( session != null )
        {
            favorite =
                (Favorite) session.createQuery( "from Favorite as favorite where favorite.nameFavorite=?" )
                    .setString( 0, nameFavorite ).uniqueResult();
            if ( favorite != null )
            {
                session.delete( favorite );
            }
        }

            updateListFavorite( nameFavorite, favorite, false );
            sort( favoritesList );


        endConnection();
    }

    /**
     * Updates a favorite show
     */
    public void updateFavoriteEpisode( String nameFavorite, String newEpisodeNumber )
    {

        if ( newEpisodeNumber.startsWith( "010" ) )
        {
            newEpisodeNumber = newEpisodeNumber.substring( 1 );
        }
        initTransaction();

        if ( session != null )
        {
            Favorite favorite =
                (Favorite) session.createQuery( "from Favorite as favorite where favorite.nameFavorite=?" )
                    .setString( 0, nameFavorite ).uniqueResult();

            if ( favorite != null )
            {
                favorite.setLastEpisodeNumber( newEpisodeNumber );
            }

            // From import
            else
            {
                favorite = new Favorite();
                favorite.setLastEpisodeNumber( newEpisodeNumber );
            }

            updateListFavorite( nameFavorite, favorite, true );

            session.update( favorite );
            endConnection();

        }

    }

    /**
     * Update or delete a favorite from the local list
     * 
     * @param nameFavorite
     * @param isUpdate is To update?
     * @param favorite the favorite to update
     */
    private void updateListFavorite( String nameFavorite, Favorite favorite, boolean isUpdate )
    {
        for ( Iterator<Favorite> itr = favoritesList.iterator(); itr.hasNext(); )
        {
            Favorite element = itr.next();
            if ( nameFavorite.equals( element.getNameFavorite() ) )
            {
                if ( isUpdate )
                {
                    element.setLastEpisodeNumber( favorite.getLastEpisodeNumber() );
                    element.setLastEpisodeNumber( favorite.getLastEpisodeNumber() );
                    element.setNameFavorite( favorite.getNameFavorite() );
                    element.setSeasonNumber( favorite.getSeasonNumber() );
                    break;
                }

                itr.remove();

            }
        }
    }

    /**
     * Inits the transaction if session !=null
     */
    private void initTransaction()
    {
        if ( hibernateUtil.getSession() != null && sqlActive )
        {
            session = hibernateUtil.getSession();
            try
            {
                transaction = session.beginTransaction();
            }
            catch ( Exception e )
            {
                LoggingTreatment.getInstance().logError( logger, "Pas de connexion sql" );
                session = null;
                sqlActive = false;

                LoggingTreatment.getInstance().logInfo( logger, "Mode SQL Inactif" );
            }
        }
    }

    /**
     * Updates a favorite show
     */
    public void updateFavorite( String nameFavorite, String seasonNumber, String episodeNumber )
    {
        initTransaction();
        Favorite favorite = null;

        if ( session != null )
        {
            favorite =
                (Favorite) session.createQuery( "from Favorite as favorite where favorite.nameFavorite=?" )
                    .setString( 0, nameFavorite ).uniqueResult();

            if ( favorite != null )
            {
                favorite.setLastEpisodeNumber( episodeNumber );
                favorite.setNameFavorite( nameFavorite );
                favorite.setSeasonNumber( seasonNumber );
            }

            session.update( favorite );
            endConnection();
        }

        // From import
        else
        {
            favorite = new Favorite();
            favorite.setLastEpisodeNumber( episodeNumber );
            favorite.setNameFavorite( nameFavorite );
            favorite.setSeasonNumber( seasonNumber );
        }

        updateListFavorite( nameFavorite, favorite, true );
        sort( favoritesList );
    }

    /**
     * Creates an instance of BddQueries
     * 
     * @return {@link BddQueries} instance
     */
    public static BddQueries getBddQueries()
    {
        if ( bddQueries == null )
        {
            bddQueries = new BddQueries();
        }
        return bddQueries;
    }

    /**
     * Return a favorite show
     * 
     * @param nameFavorite the name of the favorite
     */
    public Favorite loadFavorite( String nameFavorite )
    {
        Favorite favorite = null;
        initTransaction();

        if ( session != null )
        {
            favorite =
                (Favorite) session.createQuery( "from Favorite as favorite where favorite.nameFavorite=?" )
                    .setString( 0, nameFavorite ).uniqueResult();
        }
        // From xml
        else
        {
            for ( Iterator<Favorite> itr = favoritesList.iterator(); itr.hasNext(); )
            {
                Favorite element = itr.next();
                if ( nameFavorite.equals( element.getNameFavorite() ) )
                {
                    return element;
                }
            }
        }
        return favorite;
    }

    /**
     * @return the property path if setted
     */
    @SuppressWarnings( "unchecked" )
    public String getPropertyPath()
    {
        initTransaction();

        if ( session != null )
        {
            List<Property> prop = session.createQuery( "from Property" ).list();
            if ( null == prop || prop.isEmpty() )
            {
                return null;
            }

            return prop.get( 0 ).getPathProperty();
        }
        return null;
    }

    /**
     * Updates the property path
     * 
     * @param path the path to set
     */
    public void updatePropertyPath( String path )
    {
        initTransaction();

        if ( session != null )
        {
            Property prop = (Property) session.createQuery( "from Property" ).uniqueResult();
            if ( null == prop )
            {
                prop = new Property();
            }

            if ( null != prop && ( null == path || path.isEmpty() ) )
            {
                session.delete( prop );
                endConnection();
                return;
            }

            prop.setPathProperty( path );
            session.save( prop );
            endConnection();
        }

    }

    /**
     * Ends the connection
     */
    private void endConnection()
    {
        if ( session != null )
        {
            session.flush();
            hibernateUtil.closeConnection( transaction, session );
        }
    }

    /**
     * @return the favoritesList
     */
    public List<Favorite> getFavoritesList()
    {
        if ( favoritesList == null )
        {
            favoritesList = new ArrayList<Favorite>();
        }
        return favoritesList;
    }

    /**
     * Active le mode Sql
     */
    public void activeSql()
    {
        this.sqlActive = true;
        LoggingTreatment.getInstance().logInfo( logger, "Mode SQL Actif" );
    }

    /**
     * @return the isJobRunning
     */
    public boolean isJobRunning()
    {
        return isJobRunning;
    }

    /**
     * @param isJobRunning the isJobRunning to set
     */
    public void setJobRunning( boolean isJobRunning )
    {
        this.isJobRunning = isJobRunning;
    }

}
